package com.derbysoft.synxisadapter.dswitch3;

import com.derbysoft.dswitch.dto.hotel.avail.HotelAvailErrorDTO;
import com.derbysoft.dswitch.dto.hotel.avail.HotelAvailRQ;
import com.derbysoft.dswitch.dto.hotel.common.TransactionActionType;
import com.derbysoft.dswitch.dto.hotel.reservation.ReservationRoomStayDTO;
import com.derbysoft.dswitch.remote.hotel.dto.*;
import com.derbysoft.synxisadapter.commons.log.LogBody;
import com.derbysoft.synxisadapter.commons.log.PerformanceLogger;
import com.derbysoft.synxisadapter.commons.log.TransactionLogger;
import com.derbysoft.synxisadapter.commons.model.OperationType;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.StringUtils;

import java.util.concurrent.Executor;

/**
 * User: jason
 * Date: 2012-11-29
 */
public abstract class PerformanceHelper {

    public static void saveCancellationPerformanceLog(Executor executor, HotelCancelRequest request, HotelCancelResponse response) {
        PerformanceLogger.init();
        PerformanceLogger.append(LogBody.REQUEST_TYPE, OperationType.CANCEL_RESERVATION.name());
        PerformanceLogger.append(LogBody.ERSP_NUMBER, request.getHotelCancelRQ().getErsp());
        setPerformanceLogHeader(request);
        if (response.getError() != null) {
            TransactionLogger.getTransactionLogger().get().setError(true);
            TransactionLogger.getTransactionLogger().get().setException(response.getError().getMessage());
            PerformanceLogger.append(LogBody.PROCESSED_RESULT, LogBody.ProcessResult.Fail.name());
        } else {
            PerformanceLogger.append(LogBody.PROCESSED_RESULT, LogBody.ProcessResult.Success.name());
        }
        PerformanceLogger.save(executor);
    }

    public static void saveAvailPerformanceLog(Executor executor, HotelAvailRequest request, HotelAvailResponse response) {
        PerformanceLogger.append(LogBody.REQUEST_TYPE, OperationType.HOTEL_AVAIL.name());
        setPerformanceLogHeader(request);
        PerformanceLogger.append(LogBody.DERBY_HOTEL_CODES, getHotelCodes(request.getHotelAvailRQ()));
        PerformanceLogger.append(LogBody.CHECK_IN, request.getHotelAvailRQ().getAvailCriteria().getStayDateRange().getCheckin());
        PerformanceLogger.append(LogBody.CHECK_OUT, request.getHotelAvailRQ().getAvailCriteria().getStayDateRange().getCheckout());
        PerformanceLogger.append(LogBody.NUMBER_OF_UNIT, String.valueOf(request.getHotelAvailRQ().getAvailCriteria().getRoomStayCandidate().getNumberOfUnits()));
        PerformanceLogger.append(LogBody.ADULT, String.valueOf(request.getHotelAvailRQ().getAvailCriteria().getRoomStayCandidate().getAdultCount()));
        PerformanceLogger.append(LogBody.CHILD, String.valueOf(request.getHotelAvailRQ().getAvailCriteria().getRoomStayCandidate().getChildCount()));

        PerformanceLogger.append(LogBody.NO_ALLOTMENT, isNoAllotment(response));
        PerformanceLogger.append(LogBody.NO_AVAIL_HOTELS, getNoAvailHotels(response));
        PerformanceLogger.append(LogBody.HOTEL_AVAIL_ERRORS, getAvailErrors(response));

        if (response.getError() != null) {
            TransactionLogger.getTransactionLogger().get().setError(true);
            TransactionLogger.getTransactionLogger().get().setException(response.getError().getMessage());
            PerformanceLogger.append(LogBody.PROCESSED_RESULT, LogBody.ProcessResult.Fail.name());
        } else {
            PerformanceLogger.append(LogBody.PROCESSED_RESULT, LogBody.ProcessResult.Success.name());
        }
        PerformanceLogger.save(executor);
    }

    private static String getAvailErrors(HotelAvailResponse response) {
        StringBuilder builder = new StringBuilder();
        if (response.getHotelAvailRS() != null && CollectionUtils.isNotEmpty(response.getHotelAvailRS().getHotelAvailErrorsList())) {
            for (HotelAvailErrorDTO availErrorDTO : response.getHotelAvailRS().getHotelAvailErrorsList()) {
                builder.append(availErrorDTO.getHotelCode()).append(";");
            }
        }
        return StringUtils.isNotEmpty(builder.toString()) ? StringUtils.removeEnd(builder.toString(), ";") : "";
    }

    private static String getNoAvailHotels(HotelAvailResponse response) {
        StringBuilder builder = new StringBuilder();
        if (response.getHotelAvailRS() != null && CollectionUtils.isNotEmpty(response.getHotelAvailRS().getNoAvailHotelsList())) {
            for (String hotelCode : response.getHotelAvailRS().getNoAvailHotelsList()) {
                builder.append(hotelCode).append(";");
            }
        }
        return StringUtils.isNotEmpty(builder.toString()) ? StringUtils.removeEnd(builder.toString(), ";") : "";
    }

    private static String isNoAllotment(HotelAvailResponse response) {
        if (response.getHotelAvailRS() != null
                && CollectionUtils.isNotEmpty(response.getHotelAvailRS().getHotelAvailRoomStaysList())
                && CollectionUtils.isNotEmpty(response.getHotelAvailRS().getHotelAvailRoomStaysList().get(0).getRoomStaysList())) {
            return "false";
        }
        return "true";
    }

    public static void saveReservationPerformanceLog(Executor executor, HotelReservationRequest request, HotelReservationResponse response) {
        ReservationRoomStayDTO roomStayDTO = request.getHotelReservationRQ().getHotelReservation().getRoomStaysList().get(0);
        setPerformanceLogHeader(request);
        if (request.getHotelReservationRQ().getResActionType() == TransactionActionType.INITIATE) {
            PerformanceLogger.append(LogBody.REQUEST_TYPE, OperationType.HOTEL_PREVIEW.name());
        } else {
            PerformanceLogger.append(LogBody.REQUEST_TYPE, OperationType.HOTEL_RESERVATION.name());
        }
        PerformanceLogger.append(LogBody.DERBY_HOTEL_CODES, request.getHotelReservationRQ().getHotelReservation().getHotelCode());
        PerformanceLogger.append(LogBody.CHECK_IN, roomStayDTO.getStayDateRange().getCheckin());
        PerformanceLogger.append(LogBody.CHECK_OUT, roomStayDTO.getStayDateRange().getCheckout());
        PerformanceLogger.append(LogBody.RATE_PLAN, roomStayDTO.getRatePlanCode());
        PerformanceLogger.append(LogBody.ROOM_TYPE, roomStayDTO.getRoomTypeCode());
        PerformanceLogger.append(LogBody.NUMBER_OF_UNIT, String.valueOf(roomStayDTO.getNumberOfUnits()));
        PerformanceLogger.append(LogBody.ADULT, String.valueOf(roomStayDTO.getAdultCount()));
        PerformanceLogger.append(LogBody.CHILD, String.valueOf(roomStayDTO.getChildCount()));
        PerformanceLogger.append(LogBody.ERSP_NUMBER, request.getHotelReservationRQ().getErsp());

        if (response.getError() != null) {
            TransactionLogger.getTransactionLogger().get().setError(true);
            TransactionLogger.getTransactionLogger().get().setException(response.getError().getMessage());
            PerformanceLogger.append(LogBody.PROCESSED_RESULT, LogBody.ProcessResult.Fail.name());
        } else {
            PerformanceLogger.append(LogBody.PROCESSED_RESULT, LogBody.ProcessResult.Success.name());
        }
        PerformanceLogger.save(executor);
    }

    private static String getHotelCodes(HotelAvailRQ hotelAvailRQ) {
        StringBuilder builder = new StringBuilder();
        for (String s : hotelAvailRQ.getAvailCriteria().getHotelCodesList()) {
            builder.append(s).append(";");
        }
        return StringUtils.removeEnd(builder.toString(), ";");
    }

    private static void setPerformanceLogHeader(AbstractRQ request) {
        PerformanceLogger.append(LogBody.TASK_ID, request.getHeader().getTaskId());
        PerformanceLogger.append(LogBody.CHANNEL, request.getHeader().getSource());
        PerformanceLogger.append(LogBody.PROVIDER_CHAIN, "LowCostBeds");
    }
}
